package com.cxs.service.impl;

import com.cxs.auth.AuthRealm;
import com.cxs.contents.UserContent;
import com.cxs.dto.UserSearchDTO;
import com.cxs.enums.HospitalErrorResultEnum;
import com.cxs.exception.HospitalException;
import com.cxs.mapper.RoleMapper;
import com.cxs.mapper.UserMapper;
import com.cxs.pojo.*;
import com.cxs.service.RoleService;
import com.cxs.service.UserService;
import com.cxs.utils.QueryUtil;
import com.cxs.vo.MenuVO;
import com.cxs.vo.UserRoleVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;

/*
 * @Author:cxs
 * @Date:2021/10/15  11:48
 * @Version 1.0
 * @Motto:放下杂念,只为迎接明天更好的自己
 * */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleService roleService;

    @Autowired
    private RoleMapper roleMapper;

    @Override
    public User findUserByUsername(String loginName) {

        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        criteria.andLoginNameEqualTo(loginName);

        List<User> userList = userMapper.selectByExample(example);

        if (userList != null && userList.size() == 1) {
            User user = userList.get(0);
            if(user.getAvailable() != 1){
                log.info("【登录模块】:用户名已失效");
                throw new HospitalException(HospitalErrorResultEnum.USERNAME_EXPRISE);
            }
            return user;
        }
        return null;
    }

    @Override
    public List<MenuVO> menuList(Integer userId) {

        List<Menu> menuList = userMapper.selectMenuByUserId(userId);
        List<MenuVO> resultList = new ArrayList<>();
        Map<Integer,MenuVO> menuMap = new HashMap<>();

        // 封装一级菜单
        ListIterator<Menu> iterator = menuList.listIterator();
        while (iterator.hasNext()){
            Menu menu = iterator.next();
            if(menu.getParentId() == 1){
                MenuVO menuVO = new MenuVO();
                BeanUtils.copyProperties(menu,menuVO);
                // 判断菜单是否被展开
                if(menu.getSpread() == 1){
                    menuVO.setSpread(true);
                }
                menuMap.put(menuVO.getId(),menuVO);
                iterator.remove();
            }
        }

        for (Menu menu : menuList) {
            MenuVO pareMenuVO = menuMap.get(menu.getParentId());
            if (pareMenuVO != null){
                MenuVO menuVO = new MenuVO();
                BeanUtils.copyProperties(menu,menuVO);
                pareMenuVO.getChildren().add(menuVO);
            }
        }

        for (Map.Entry<Integer, MenuVO> entry : menuMap.entrySet()) {
            resultList.add(entry.getValue());
        }

        return resultList;
    }

    @Override
    public PageInfo<User> findUserBySearch(UserSearchDTO searchDTO, Integer pageNo, Integer limit) {

        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();

        if(!StringUtils.isEmpty(searchDTO.getLoginname())){
            criteria.andLoginNameLike(QueryUtil.createLikeResult(searchDTO.getLoginname()));
        }

        if(!StringUtils.isEmpty(searchDTO.getRealname())){
            criteria.andRealNameLike(QueryUtil.createLikeResult(searchDTO.getRealname()));
        }

        if(!StringUtils.isEmpty(searchDTO.getAddress())){
            criteria.andAddressLike(QueryUtil.createLikeResult(searchDTO.getAddress()));
        }

        if(!StringUtils.isEmpty(searchDTO.getIdentity())){
            criteria.andIdentityLike(QueryUtil.createLikeResult(searchDTO.getIdentity()));
        }

        if(!StringUtils.isEmpty(searchDTO.getPhone())){
            criteria.andPhoneEqualTo(searchDTO.getPhone());
        }

        PageHelper.startPage(pageNo,limit);

        List<User> userList = userMapper.selectByExample(example);

        return new PageInfo<User>(userList);
    }

    @Override
    @Transactional
    public void addUser(User user) {
        // 获取初始密码
        String password = UserContent.INIT_PWD;
        // 密码加密
        String salt = UUID.randomUUID().toString().replace("-","");
        String pwd = new Md5Hash(password,salt, UserContent.INIT_HASH).toString();

        user.setPwd(pwd);

        user.setSalt(salt);

        user.setType(UserContent.USER_TYPE_SYSTEM);

        // 用户添加
        int result = userMapper.insertSelective(user);
        if(result != 1){
            log.error("【添加用户】:用户添加失败 user = {}",user);
            throw new HospitalException(HospitalErrorResultEnum.USER_SAVE_USER_ERROR);
        }

    }

    @Override
    public List<UserRoleVO> getinitUserRoleInfo(Integer userid) {

        // 查询所有角色信息
        List<Role> roleList = roleService.selectAll();

        // 查询用户拥有的角色信息
        List<Role> userRoleList = roleMapper.selectByuserId(userid);

        List<UserRoleVO> list = new ArrayList<>();

        for (Role role : roleList) {
            UserRoleVO userRoleVO = new UserRoleVO();
            BeanUtils.copyProperties(role,userRoleVO);
            if(userRoleList.contains(role)){
                userRoleVO.setChecked(true);
            }
            list.add(userRoleVO);
        }

        return list;
    }

    @Override
    @Transactional
    public void updateUserRole(Integer userid, List<Integer> ids) {
        // 1. 清除用户原有的角色
        Integer result = userMapper.clearRole(userid);
        // 2. 赋予用户新的角色
        Integer count = userMapper.saveRoleToUser(userid,ids);

        if(count != ids.size()){
            log.error("【赋予角色】:授予新角色失败,userid = {},ids = {}",userid,ids);
            throw new HospitalException(HospitalErrorResultEnum.USER_SAVE_USER_ROLE_ERROR);
        }
    }

    @Override
    public void delete(Integer userId) {
        int result = userMapper.deleteByPrimaryKey(userId);
        if(result != 1){
            log.error("【删除用户】:用户删除失败 userId = {}",userId);
            throw new HospitalException(HospitalErrorResultEnum.USER_DELETE_USER_ERROR);
        }
    }

    @Override
    public void update(User user) {
        int result = userMapper.updateByPrimaryKeySelective(user);
        if(result != 1){
            log.error("【修改用户】:用户修改失败 user = {}",user);
            throw new HospitalException(HospitalErrorResultEnum.USER_UPDATE_USER_ERROR);
        }
    }

    @Override
    public void initPwd(Integer userId){
        User user = new User();
        String salt = UUID.randomUUID().toString().replace("-","");
        String pwd = new Md5Hash(UserContent.INIT_PWD, salt,UserContent.INIT_HASH).toString();
        user.setUserId(userId);
        user.setPwd(pwd);
        user.setSalt(salt);

        int result = userMapper.updateByPrimaryKeySelective(user);
        if(result != 1){
            log.error("【密码重置】:密码重置失败 user = {}",user);
            throw new HospitalException(HospitalErrorResultEnum.USER_PWD_INIT_ERROR);
        }
    }
}
